#include "Scene1.h"
#include <list>
#include "BuildFunctions.h"
#include "ImageFunctions.h"


void Scene1::InitializeTextures()
{
	BuildTexture("wall01.jpg",   GetTexture(0));  // wall texture
    BuildTexture("tile01.jpg",   GetTexture(1));  // floor texture
    BuildTexture("tile02.jpg",   GetTexture(2));  // ceiling texture
	wallTexture    = GetTexture(0);
	floorTexture   = GetTexture(1);
	ceilingTexture = GetTexture(2);
}

void Scene1::Build()
{
    InitializeTextures();
	BuildRoom();
	BuildCourtyard();
	BuildCastle();
}
void Scene1::BuildCastle()
{
	vec<float,4> topLeftPoint,topLeftColor,bottomRightPoint,bottomRightColor;
	topLeftPoint       =  45,  20,   6,   1;
	topLeftColor       =   0,   0,   0,   1;
	bottomRightPoint   =  45,  -5, -70,   1;
	bottomRightColor   =   0,   0,   0,   1;
	float topLeftS     =   0;
	float topLeftF     =   0;
	float bottomRightS =   6;
	float bottomRightF =   4;
	float wallWidth    =   3;
	float cubeLength   =   3;
    BuildRightCastleWall(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength);

	topLeftPoint[0]     = -45 + wallWidth;
	bottomRightPoint[0] = -45 + wallWidth;
	BuildRightCastleWall(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength);

	topLeftPoint     = -45,  20, -70+wallWidth, 1;
	bottomRightPoint =  45,  -5, -70+wallWidth, 1;
	BuildFrontCastleWall(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength);

	topLeftPoint     = -45,  20,  6, 1;
	bottomRightPoint =  45,  -5,  6, 1;
	BuildCastleEntrance(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength, 10, 10);
}
void Scene1::BuildCourtyard()
{
	float lrp =   70;  // left  right perimeter
	float fbp =  120;  // front back  perimeter
	float eh  =   20;  // extra height
	vec<float,4> topLeftPoint,topLeftColor,bottomRightPoint,bottomRightColor;
	topLeftPoint       =  45+lrp,  20+eh,   6+fbp,   1;
	topLeftColor       =       0,      0,       0,   1;
	bottomRightPoint   =  45+lrp,     -5, -70-fbp,   1;
	bottomRightColor   =       0,      0,       0,   1;
	float topLeftS     =       0;
	float topLeftF     =       0;
	float bottomRightS =       6;
	float bottomRightF =       4;
	float wallWidth    =       6;
	float cubeLength   =       3;
    BuildRightCastleWall(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength);

	topLeftPoint[0]     = -45 + wallWidth - lrp;
	bottomRightPoint[0] = -45 + wallWidth - lrp;
	BuildRightCastleWall(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength);

	topLeftPoint     = -45-lrp,  20+eh, -70+wallWidth-fbp, 1;
	bottomRightPoint =  45+lrp,     -5, -70+wallWidth-fbp, 1;
	BuildFrontCastleWall(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength);

	topLeftPoint     = -45-lrp,  20+eh, 6+fbp, 1;
	bottomRightPoint =  45+lrp,     -5, 6+fbp, 1;
	BuildCastleEntrance(
		topLeftPoint, topLeftColor, topLeftS, topLeftF, 
		bottomRightPoint, bottomRightColor, bottomRightS, bottomRightF, 
		wallWidth, cubeLength, 12, 20);
}
void Scene1::BuildRoom()
{
    vec<float,4> pos1,col1,pos2,col2,normal; 
    col1 = 0,0,0,1;
    col2 = 0,0,0,1;
    float x_min  =  -5;
    float x_max  =   5;
    float y_min  =  -5;
    float y_max  =   5;
    float z_in   = -15;
    float z_out  =   6;
    float startS =   0;
    float endS   = 2.5;
    float startF =   0;
    float endF   = 2.5;

	/*
    // Front Wall
    norm = 0,0,1,1;
    pos1 = x_min, y_max, z_in, 1;
    pos2 = x_max, y_min, z_in, 1;
    buildQuad(shapes, norm, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);
	*/

    // Right Wall
    normal = -1,0,0,1;
    pos1 = x_max, y_max, z_in,  1;
    pos2 = x_max, y_min, z_out, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

    // Left Wall
    normal = 1,0,0,1;
    pos1 = x_min, y_max, z_out, 1;
    pos2 = x_min, y_min, z_in,  1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

    // Floor
    normal = 0,1,0,1;
    pos1 = x_min, y_min, z_in,  1;
    pos2 = x_max, y_min, z_out, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, floorTexture);

    // Ceiling
    normal = 0,-1,0,1;
    pos1 = x_min, y_max, z_out, 1;
    pos2 = x_max, y_max, z_in,  1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, ceilingTexture);
}

void Scene1::BuildCastleEntrance(
		vec<float,4> topLeftPoint,
		vec<float,4> topLeftColor,
		float        topLeftS, 
		float		 topLeftF,
		vec<float,4> bottomRightPoint,
		vec<float,4> bottomRightColor,
		float        bottomRightS, 
		float        bottomRightF,
		float        wallWidth,
		float        cubeLength,
		float        entranceWidth,
		float        entranceHeight)
{
    vec<float,4> normal,col1,col2,pos1,pos2; 
    col1 = 0,0,0,1;
    col2 = 0,0,0,1;
    float x_min  =  topLeftPoint[0];
    float x_max  =  bottomRightPoint[0];
	float x_loe  =  topLeftPoint[0] + (bottomRightPoint[0] - topLeftPoint[0] - entranceWidth)/2 ;  // left of entrance
	float x_roe  =  topLeftPoint[0] + (bottomRightPoint[0] - topLeftPoint[0] + entranceWidth)/2 ;  // right of entrance
    float y_min  =  bottomRightPoint[1];
    float y_max  =  topLeftPoint[1];
	float y_e    =  bottomRightPoint[1]+entranceHeight;              // entrance height
	float y_c    =  topLeftPoint[1]+cubeLength;  // top of cube
    float z_in   =  topLeftPoint[2]-wallWidth;
    float z_out  =  topLeftPoint[2];
    float startS =  topLeftS;
    float endS   =  bottomRightS;
    float startF =  topLeftF;
    float endF   =  bottomRightF;

    normal = 0,0,1,1;
	// Front side of wall Left of entrance
    pos1 = x_min, y_e,   z_out, 1;
    pos2 = x_loe, y_min, z_out, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

    // Front side of wall Right of entrance
    pos1 = x_roe, y_e,   z_out, 1;
    pos2 = x_max, y_min, z_out, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

	// Front side of wall Above entrance
    pos1 = x_min, y_max,   z_out, 1;
    pos2 = x_max, y_e ,    z_out, 1;
	endS = 12;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

    normal = 0,0,-1,1;
	// Back side of wall Left of entrance
	normal = normal * -1; normal[3] = 1;
    pos1 = x_loe, y_e,   z_in, 1;
    pos2 = x_min, y_min, z_in, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

    // Back side of wall Right of entrance
    pos1 = x_max, y_e,   z_in, 1;
    pos2 = x_roe, y_min, z_in, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

	// Back side of wall Above entrance
    pos1 = x_max, y_max,   z_in, 1;
    pos2 = x_min, y_e ,    z_in, 1;
	endS = 12;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

	// Show Top Cubes
	const int increment = 2*cubeLength;
	endS = 1;
	endF = 1;
	for (int l = x_min; l <= x_max-cubeLength*3; l+=increment)
	{
		float r = l + cubeLength;

		// front face of cube
		normal = 0,0,1,1;
		pos1 = l, y_c,   z_out, 1;
		pos2 = r, y_max, z_out, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// back face of cube
		normal = 0,0,-1,1;
		pos1 = r, y_c,   z_in, 1;
		pos2 = l, y_max, z_in, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// right face of cube
		normal = 1,0,0,1;
		pos1 = r, y_c,   z_out, 1;
		pos2 = r, y_max, z_in,  1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// left face of cube
		normal = -1,0,0,1;
		pos1 = l, y_c,   z_in,  1;
		pos2 = l, y_max, z_out, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);
	}
}
void Scene1::BuildRightCastleWall(
	vec<float,4> topLeftPoint,
	vec<float,4> topLeftColor,
	float        topLeftS, 
	float		 topLeftF,
	vec<float,4> bottomRightPoint,
	vec<float,4> bottomRightColor,
	float        bottomRightS, 
	float        bottomRightF,
	float        wallWidth,
	float        cubeLength)
{
    vec<float,4> normal,col1,col2,pos1,pos2; 
    col1 = 0,0,0,1;
    col2 = 0,0,0,1;
    float x_min  =   topLeftPoint[0] - wallWidth;
    float x_max  =   topLeftPoint[0];
    float y_min  =   bottomRightPoint[1];
    float y_max  =   topLeftPoint[1];
	float y_c    =   topLeftPoint[1] + cubeLength;  // top of cube
    float z_in   =   bottomRightPoint[2];
    float z_out  =   topLeftPoint[2];
    float startS =   topLeftS;
    float endS   =   bottomRightS;
    float startF =   topLeftF;
    float endF   =   bottomRightF;

	// Right Wall
    normal = 1,0,0,1;
    pos1 = x_max, y_max, z_out, 1;
    pos2 = x_max, y_min, z_in,  1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

    // Left Wall
	normal = -1,0,0,1;
    pos1 = x_min, y_max, z_in,  1;
    pos2 = x_min, y_min, z_out, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

	// Show Top Cubes
	const int increment = 2*cubeLength;
	endS = .3;
	endF = .3;
	for (int out = z_out; out >= z_in+cubeLength*3; out-=increment)
    {
        float in = out - cubeLength;

		// front face of cube
		normal = 0,0,1,1;
		pos1 = x_min, y_c,   out, 1;
		pos2 = x_max, y_max, out, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// back face of cube
		normal = 0,0,-1,1;
		pos1 = x_max, y_c,   in, 1;
		pos2 = x_min, y_max, in, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// right face of cube
		normal = 0,0,1,1;
		pos1 = x_max, y_c,   out, 1;
		pos2 = x_max, y_max, in,  1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// left face of cube
		normal = -1,0,0,1;
		pos1 = x_min, y_c,   in,  1;
		pos2 = x_min, y_max, out, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);
	}
}

void Scene1::BuildFrontCastleWall(
	vec<float,4> topLeftPoint,
	vec<float,4> topLeftColor,
	float        topLeftS, 
	float		 topLeftF,
	vec<float,4> bottomRightPoint,
	vec<float,4> bottomRightColor,
	float        bottomRightS, 
	float        bottomRightF,
	float        wallWidth,
	float        cubeLength)
{
    vec<float,4> normal,col1,col2,pos1,pos2; 
    col1 = 0,0,0,1;
    col2 = 0,0,0,1;
    float x_min  =   topLeftPoint[0];
    float x_max  =   bottomRightPoint[0];
    float y_min  =   bottomRightPoint[1];
    float y_max  =   topLeftPoint[1];
	float y_c    =   topLeftPoint[1] + cubeLength;  // top of cube
    float z_in   =   topLeftPoint[2] - wallWidth;
    float z_out  =   topLeftPoint[2];
    float startS =   topLeftS;
    float endS   =   bottomRightS;
    float startF =   topLeftF;
    float endF   =   bottomRightF;

	// Front Wall
    normal = 0,0,1,1;
    pos1 = x_min, y_max, z_out, 1;
    pos2 = x_max, y_min, z_out, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

    // Back Wall
    normal = 0,0,-1,1;
    pos1 = x_max, y_max, z_in, 1;
    pos2 = x_min, y_min, z_in, 1;
    buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

	// Show Top Cubes
	const int increment = 2 * cubeLength;
	endS = .3;
	endF = .3;
	for (int l = x_min; l <= x_max-cubeLength*3; l+=increment)
	{
		float r = l + cubeLength;

		// front face of cube
		normal = 0,0,1,1;
		pos1 = l, y_c,   z_out, 1;
		pos2 = r, y_max, z_out, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// back face of cube
		normal = 0,0,-1,1;
		pos1 = r, y_c,   z_in, 1;
		pos2 = l, y_max, z_in, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// right face of cube
		normal = 1,0,0,1;
		pos1 = r, y_c,   z_out, 1;
		pos2 = r, y_max, z_in,  1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);

		// left face of cube
		normal = -1,0,0,1;
		pos1 = l, y_c,   z_in,  1;
		pos2 = l, y_max, z_out, 1;
		buildQuad(shapes, normal, pos1, col1, startS, startF, pos2, col2, endS, endF, wallTexture);
	}
}